﻿using System;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Web.Hosting;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;
using Xenta;

namespace IisHost.UI
{
    public partial class NHibernateControl : UserControl
    {
        public string Infrastructure
        {
            get
            {
                return ViewState["Infrastructure"] as String;
            }
            set
            {
                ViewState["Infrastructure"] = value;
            }
        }

        private string FilePath
        {
            get
            {
                return Path.Combine(HostingEnvironment.MapPath("~/App_Data"), 
                    Infrastructure, 
                    InfrastructureImpl.NH_CFG_FILENAME);
            }
        }

        public void BindData()
        {
            lblMessage.Visible = false;

            try
            {
                var xCfg = XElement.Load(FilePath);
                var xNs = xCfg.GetDefaultNamespace();
                var xFactory = xCfg.Element(xNs.GetName("session-factory"));
                var xProperties = xFactory.Elements(xNs.GetName("property"));

                foreach(var i in xProperties)
                {
                    switch(i.Attribute("name").Value)
                    {
                        case "connection.provider":
                            txtConnection_Provider.Text = i.Value;
                            break;
                        case "connection.driver_class":
                            txtConnection_DriverClass.Text = i.Value;
                            break;
                        case "connection.connection_string":
                            txtConnection_ConnectionString.Text = i.Value;
                            break;
                        case "show_sql":
                            txtShowSql.Text = i.Value;
                            break;
                        case "prepare_sql":
                            txtPrepareSql.Text = i.Value;
                            break;
                        case "generate_statistics":
                            txtGenerateStatistics.Text = i.Value;
                            break;
                        case "dialect":
                            txtDialect.Text = i.Value;
                            break;
                        case "cache.use_second_level_cache":
                            txtCache_UseSecondLevelCache.Text = i.Value;
                            break;
                        case "cache.use_query_cache":
                            txtCache_UseQueryCache.Text = i.Value;
                            break;
                        case "cache.region_prefix":
                            txtCache_RegionPrefix.Text = i.Value;
                            break;
                        case "cache.provider_class":
                            txtCache_ProviderClass.Text = i.Value;
                            break;
                        case "max_fetch_depth":
                            txtMaxFetchDepth.Text = i.Value;
                            break;
                    }
                }
            }
            catch(Exception ex)
            {
                lblMessage.Visible = true;
                lblMessage.ForeColor = Color.Red;
                lblMessage.Text = ex.Message;
            }
        }

        protected void OnCommand(object sender, CommandEventArgs e)
        {
            switch(e.CommandName)
            {
                case "Save":
                    {
                        string connection_Provider = txtConnection_Provider.Text.Trim();
                        string connection_DriverClass = txtConnection_DriverClass.Text.Trim();
                        string connection_ConnectionString = txtConnection_ConnectionString.Text.Trim();
                        string showSql = txtShowSql.Text.Trim();
                        string prepareSql = txtPrepareSql.Text.Trim();
                        string generateStatistics = txtGenerateStatistics.Text.Trim();
                        string dialect = txtDialect.Text.Trim();
                        string cache_UseSecondLevelCache = txtCache_UseSecondLevelCache.Text.Trim();
                        string cache_UseQueryCache = txtCache_UseQueryCache.Text.Trim();
                        string cache_RegionPrefix = txtCache_RegionPrefix.Text.Trim();
                        string cache_ProviderClass = txtCache_ProviderClass.Text.Trim();
                        string maxFetchDepth = txtMaxFetchDepth.Text.Trim();

                        try
                        {
                            var xCfg = XElement.Load(FilePath);
                            var xNs = xCfg.GetDefaultNamespace();
                            var xFactory = xCfg.Element(xNs.GetName("session-factory"));
                            var xProperties = xFactory.Elements(xNs.GetName("property"));

                            // connection.provider
                            var xConnection_Provider = xProperties.SingleOrDefault(x => 
                                x.Attribute("name").Value == "connection.provider");
                            if(xConnection_Provider == null)
                                xFactory.Add(new XElement(xNs.GetName("property"), 
                                    new XAttribute("name", "connection.provider"),
                                    new XText(connection_Provider)));
                            else
                                xConnection_Provider.SetValue(connection_Provider);

                            // connection.driver_class
                            var xConnection_DriverClass = xProperties.SingleOrDefault(x =>
                                x.Attribute("name").Value == "connection.driver_class");
                            if(xConnection_DriverClass == null)
                                xFactory.Add(new XElement(xNs.GetName("property"),
                                    new XAttribute("name", "connection.driver_class"),
                                    new XText(connection_DriverClass)));
                            else
                                xConnection_DriverClass.SetValue(connection_DriverClass);

                            // connection.connection_string
                            var xConnection_ConnectionString = xProperties.SingleOrDefault(x =>
                                x.Attribute("name").Value == "connection.connection_string");
                            if(xConnection_ConnectionString == null)
                                xFactory.Add(new XElement(xNs.GetName("property"),
                                    new XAttribute("name", "connection.connection_string"),
                                    new XText(connection_ConnectionString)));
                            else
                                xConnection_ConnectionString.SetValue(connection_ConnectionString);

                            // show_sql
                            var xShowSql = xProperties.SingleOrDefault(x =>
                                x.Attribute("name").Value == "show_sql");
                            if(xShowSql == null)
                                xFactory.Add(new XElement(xNs.GetName("property"),
                                    new XAttribute("name", "show_sql"),
                                    new XText(showSql)));
                            else
                                xShowSql.SetValue(showSql);

                            // prepare_sql
                            var xPrepareSql = xProperties.SingleOrDefault(x =>
                                x.Attribute("name").Value == "prepare_sql");
                            if(xPrepareSql == null)
                                xFactory.Add(new XElement(xNs.GetName("property"),
                                    new XAttribute("name", "prepare_sql"),
                                    new XText(prepareSql)));
                            else
                                xPrepareSql.SetValue(prepareSql);

                            // generate_statistics
                            var xGenerateStatistics = xProperties.SingleOrDefault(x =>
                                x.Attribute("name").Value == "generate_statistics");
                            if(xGenerateStatistics == null)
                                xFactory.Add(new XElement(xNs.GetName("property"),
                                    new XAttribute("name", "generate_statistics"),
                                    new XText(generateStatistics)));
                            else
                                xGenerateStatistics.SetValue(generateStatistics);

                            // dialect
                            var xDialect = xProperties.SingleOrDefault(x =>
                                x.Attribute("name").Value == "dialect");
                            if(xDialect == null)
                                xFactory.Add(new XElement(xNs.GetName("property"),
                                    new XAttribute("name", "dialect"),
                                    new XText(dialect)));
                            else
                                xDialect.SetValue(dialect);

                            // cache.use_second_level_cache
                            var xCache_UseSecondLevelCache = xProperties.SingleOrDefault(x =>
                                x.Attribute("name").Value == "cache.use_second_level_cache");
                            if(xCache_UseSecondLevelCache == null)
                                xFactory.Add(new XElement(xNs.GetName("property"),
                                    new XAttribute("name", "cache.use_second_level_cache"),
                                    new XText(cache_UseSecondLevelCache)));
                            else
                                xCache_UseSecondLevelCache.SetValue(cache_UseSecondLevelCache);

                            // cache.use_query_cach
                            var xCache_UseQueryCache = xProperties.SingleOrDefault(x =>
                                x.Attribute("name").Value == "cache.use_query_cache");
                            if(xCache_UseQueryCache == null)
                                xFactory.Add(new XElement(xNs.GetName("property"),
                                    new XAttribute("name", "cache.use_query_cache"),
                                    new XText(cache_UseQueryCache)));
                            else
                                xCache_UseQueryCache.SetValue(cache_UseQueryCache);

                            // cache.region_prefix
                            var xCache_RegionPrefix = xProperties.SingleOrDefault(x =>
                                x.Attribute("name").Value == "cache.region_prefix");
                            if(xCache_RegionPrefix == null)
                                xFactory.Add(new XElement(xNs.GetName("property"),
                                    new XAttribute("name", "cache.region_prefix"),
                                    new XText(cache_RegionPrefix)));
                            else
                                xCache_RegionPrefix.SetValue(cache_RegionPrefix);

                            // cache.provider_class
                            var xCache_ProviderClass = xProperties.SingleOrDefault(x =>
                                x.Attribute("name").Value == "cache.provider_class");
                            if(xCache_ProviderClass == null)
                                xFactory.Add(new XElement(xNs.GetName("property"),
                                    new XAttribute("name", "cache.provider_class"),
                                    new XText(cache_ProviderClass)));
                            else
                                xCache_ProviderClass.SetValue(cache_ProviderClass);

                            // max_fetch_depth
                            var xMaxFetchDepth = xProperties.SingleOrDefault(x =>
                                x.Attribute("name").Value == "max_fetch_depth");
                            if(xMaxFetchDepth == null)
                                xFactory.Add(new XElement(xNs.GetName("property"),
                                    new XAttribute("name", "max_fetch_depth"),
                                    new XText(maxFetchDepth)));
                            else
                                xMaxFetchDepth.SetValue(maxFetchDepth);

                            xCfg.Save(FilePath);

                            lblMessage.ForeColor = Color.Green;
                            lblMessage.Text = "Operation completed successfully.";
                        }
                        catch(Exception ex)
                        {
                            lblMessage.ForeColor = Color.Red;
                            lblMessage.Text = ex.Message;
                        }
                        lblMessage.Visible = true;
                    }
                    break;
            }
        }
    }
}